//--------------------------------------------------------------------
#include <stdio.h>
#include <avr/io.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>

#include "dkbasic.h"
#include "dkstatements.h"
#include "dkexpression.h"
#include "dkstring.h"
#include "dktables.h"
#include "dkprogram.h"


//--------------------------------------------------------------------

char *dkinterpretline( char *line )
{
	char t[MAX_TOKEN_LENGTH+1];
	char * (*statementhandler)(char *str) = NULL;
	char *lptr;
	uint16_t nameflags;
	struct _dkfornext *oldfornext;
	struct _dkwhilewend *oldwhilewend;
	dkexpression *e;
	

	if( dkstatus != DKSTATUS_SKIPTONEXT )
		dkstatus = DKSTATUS_OK;					// default to 'ok' status

	if( dktrace && dkPC )
		printf_P( PSTR("[%d]"), dkPC );
											

	while( line[0] && ( dkstatus<DKSTATUS_BREAKLINE ) )	// loop to process all statements on line
	{
		lptr = line;
		line = dkgettoken( line, t );			// get first token from the line (to see if it's a line number)
		if( !t[0] )								// no first token - nothing to process on this line
			break;

		if( dkstatus == DKSTATUS_SKIPTOWEND )
		{										// skip execution of lines until the WEND matching previous WHILE is found
			// check t for 'next'
			if( !strcmp_P( t, PSTR("wend") ) )
			{
				dkstatus = DKSTATUS_OK;			// WEND was found
				oldwhilewend = dkwhilewendstack;
				dkwhilewendstack = dkwhilewendstack->next;		// remove item from dkwhilewendstack list
				free( oldwhilewend );
			}

			while( (t[0] != ':') && t[0] )		// eat up all tokens until line ends or ':'
				line = dkgettoken( line, t );

			continue;			
		}
		if( dkstatus == DKSTATUS_SKIPTONEXT )
		{										// skip execution of lines until the NEXT matching previous FOR is found
			// check t for 'next'
			if( !strcmp_P( t, PSTR("next") ) )
			{
				if( !dkfornextstack )
					break;

				// check if it is correct next
				lptr = dkgettoken( line, t );			// gettoken to get variable name
				if( !isalpha( t[0] ) )
				{
					dkstatus = DKSTATUS_OK;
					oldfornext = dkfornextstack;
					dkfornextstack = dkfornextstack->next;		// remove item from dkfornextstack list
					free( oldfornext->var->name );
					free( oldfornext->var );
					free( oldfornext );
					break;
				}

				line = dkgetnameflags( lptr, &nameflags );
				if(!nameflags)
					nameflags = DKVAR_DEFAULT;

				if( nameflags&DKNAME_INTEGER )
				{									// name specifies integer
					if( (!strcmp( t, dkfornextstack->var->name )) && (dkfornextstack->var->e.type==DKVAR_INTEGER) )
						dkstatus = DKSTATUS_OK;		// found next, remove DKSTATUS_SKIPTONEXT
				}
				else if( nameflags&DKNAME_STRING )
					;
				else if( nameflags&DKNAME_FLOATSINGLE )	// name specifies floatsingle
				{									// name specifies integer
					if( (!strcmp( t, dkfornextstack->var->name )) && (dkfornextstack->var->e.type==DKVAR_FLOATSINGLE) )
						dkstatus = DKSTATUS_OK;		// found next, remove DKSTATUS_SKIPTONEXT
				}
				else if( nameflags&DKNAME_FLOATDOUBLE )	// name specifies floatdouble
				{									// name specifies integer
					if( (!strcmp( t, dkfornextstack->var->name )) && (dkfornextstack->var->e.type==DKVAR_FLOATDOUBLE) )
						dkstatus = DKSTATUS_OK;		// found next, remove DKSTATUS_SKIPTONEXT
				}

				if( dkstatus != DKSTATUS_SKIPTONEXT )
				{
					oldfornext = dkfornextstack;
					dkfornextstack = dkfornextstack->next;		// remove item from dkfornextstack list
					free( oldfornext->var->name );
					free( oldfornext->var );
					free( oldfornext );
				}
			}

			while( (t[0] != ':') && t[0] )		// eat up all tokens until line ends or ':'
				line = dkgettoken( line, t );

			continue;			
		}


		statementhandler = dkfindstatement( t );
		if( statementhandler )
			line = statementhandler( line );	// found statementhandler() for this statement, execute it
		else
		{										// unknown statement - is it an assignment to a variable?
			line = dkgettoken( lptr, t );		// get first token in t (variable name)			
			line = dkgetnameflags( line, &nameflags );
			if( nameflags & DKNAME_PAREN )
			{
				e=dkgetfirstexpression( line );
				while(e)
				{					
					dkexpfree(e);
					e=dkgetnextexpression( expstr );
				}
				line = expstr;
			}
			line = dkgettoken( line, t );		// get next token - should be '='
			if( t[0]=='=' )
				line = dkstatement_let( lptr ); // found assignment, process line as a LET statement
			else
			{
				dkstatus = DKSTATUS_SYNTAXERROR; // not an assignment (and unknown statement) - syntax error
				break;
			}
		}
		line = dkgettoken( line, t );			// get next token from the line

		if( t[0] != ':' && t[0] != '\0' )
		{
			dkstatus = DKSTATUS_SYNTAXERROR;
			break;								// more tokens on line, but not a ':' separator - syntax error
		}
	}

	return line;
}

//--------------------------------------------------------------------

